package com.ltkj.baseplatform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import com.ltkj.baseplatform.domain.WuserExt;
import com.ltkj.baseplatform.feign.RemoteSysemUserService;
import com.ltkj.baseplatform.mapper.WuserExtMapper;
import com.ltkj.baseplatform.service.IsendMessage;
import com.ltkj.baseplatform.util.SendSmsAliUtil;
import com.ltkj.baseplatform.util.SendSmsUtil;
import com.ltkj.common.core.constant.SecurityConstants;
import com.ltkj.common.core.domain.R;
import com.ltkj.common.core.exception.ServiceException;
import com.ltkj.common.core.utils.StringUtils;
import com.ltkj.common.core.web.domain.AjaxResult;
import com.ltkj.common.redis.service.RedisService;
import com.ltkj.system.api.RemoteLogService;
import com.ltkj.system.api.domain.SysOperLog;
import com.ltkj.system.api.domain.SysUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @Author: chenzeen
 * @Date: 2023/08/31
 * @Description:
 */
@Service
@RefreshScope
public class SendMessageImpl implements IsendMessage {
    private static final Logger log = LoggerFactory.getLogger(SendMessageImpl.class);

    @Autowired
    private RedisService redisService;

    @Autowired
    private WuserExtMapper wuserExtMapper;

    @Autowired
    private RemoteSysemUserService remoteSysemUserService;

    @Autowired
    private SendSmsUtil sendSmsUtil;

    @Autowired
    private SendSmsAliUtil sendSmsAliUtil;

    @Autowired
    private RemoteLogService remoteLogService;

    @Value("${wx.messageTimeOut}")
    private Long timeOut;

    @Value("${wx.codeUsable}")
    private Long codeUsable;

    @Value("${wx.smsChunnel}")
    private String smsChunnel;

    @Value("${wx.smsTempCode}")
    private String smsTempCode;

    private final String MESSAGE_REDIS = "message:";

    /**
     * 发送验证码
     * @param phone
     * @return
     */
    @Override
    public AjaxResult sendmessage(String phone) {
        //从redis获取值,如果没有,发送短信,redis赋值
        boolean flag = redisService.hasKey(MESSAGE_REDIS+phone);
        if(!flag) {
            //没有这个key说明,最近没有发送过短信

            //发送短信
            String code = RandomUtil.randomNumbers(4);
            JSONObject entries = new JSONObject();
            entries.set("code",code);
            String jsonString = com.alibaba.fastjson.JSONObject.toJSONString(entries);
            AjaxResult ar = AjaxResult.error();
            if (smsChunnel.equals("1")) {
                ar = sendSmsAliUtil.sendSms(smsTempCode, entries.toString(), phone);
            } else if (smsChunnel.equals("2")) {
                ar = sendSmsUtil.sendSms(phone,"","", jsonString);
            }

            if(ar.isSuccess()){
                //放入reidis,设置过期时间
                redisService.setCacheObject(MESSAGE_REDIS+phone, 1,timeOut,TimeUnit.MINUTES);
                //将code存入缓存
                redisService.setCacheObject(MESSAGE_REDIS+phone+"-code",code,codeUsable,TimeUnit.MINUTES);
                //成功发送的可在天翼云控制台查看
                return AjaxResult.success("发送成功");
            } else {
                //写入失败日志,日志通过网关页面查看
                try {
                    SysOperLog sysOperLog = new SysOperLog();
                    sysOperLog.setTitle("发送短信失败");
                    sysOperLog.setBusinessType(0);
                    sysOperLog.setMethod("sendmessage");
                    sysOperLog.setOperParam(phone+";"+jsonString);
                    sysOperLog.setJsonResult(""+ar.get(AjaxResult.DATA_TAG));
                    sysOperLog.setStatus(1);
                    sysOperLog.setErrorMsg(""+ar.get(AjaxResult.MSG_TAG));
                    sysOperLog.setOperTime(new Date());
                    remoteLogService.saveLog(sysOperLog, SecurityConstants.INNER);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("短信调用失败,往数据库写错误日志失败,"+e.getMessage());
                }
                return ar;
            }
        } else {
            //如果有值,说明刚有发送过
            return AjaxResult.error("请稍后发送验证码");
        }
    }

    /**
     * 验证手机号
     * @param phone
     * @return
     */
    @Override
    @Transactional
//    @GlobalTransactional
    public AjaxResult checkPhoneCode(String phone,String code) {
        //从redis中 获取code
        String codeR = redisService.getCacheObject(MESSAGE_REDIS+phone+"-code");
        if(StringUtils.equals(code, codeR)) {
            //验证成功,修改用户验证状态
            AjaxResult ar = remoteSysemUserService.getInfoByLogin();
            if(ar.isSuccess()) {
                if(ar.get("data") != null ) {
                    SysUser sysUser = BeanUtil.mapToBean((LinkedHashMap)ar.get("data"),SysUser.class,true);
                    WuserExt wuserExt = wuserExtMapper.selectWuserExtByUserId(sysUser.getUserId());
                    wuserExt.setPhoneAuth("0");
                    int i = wuserExtMapper.updateWuserExt(wuserExt);
                    if(i > 0){
                        //设置手机号
                        sysUser.setPhonenumber(phone);
                        R r = remoteSysemUserService.editUser(sysUser, SecurityConstants.INNER);
                        if (StringUtils.isNull(r) || r.getCode() != 200)
                        {
                            throw new ServiceException("修改用户服务异常!");
                        }
                    }
                }
                return AjaxResult.success("验证成功");
            } else {
                return AjaxResult.error("获取用户信息失败");
            }
        } else {
            return AjaxResult.error("验证码不正确");
        }
    }

    /**
     * 只验证验证手机号
     * @param phone 手机号
     * @param code 验证码
     * @return AjaxResult
     */
    @Override
    @Transactional
    public AjaxResult checkPhoneCodeAtom(String phone, String code) {
        //从redis中 获取code
        String codeR = redisService.getCacheObject(MESSAGE_REDIS+phone+"-code");
        if(StringUtils.equals(code, codeR)) {
            return AjaxResult.success("验证成功");
        } else {
            return AjaxResult.error("验证码不正确");
        }
    }

    @Override
//    @GlobalTransactional
    public AjaxResult testSeata() {
        SysOperLog sysOperLog = new SysOperLog();
        sysOperLog.setTitle("测试分布式事务");
        sysOperLog.setBusinessType(99);
        sysOperLog.setMethod("test");
        sysOperLog.setOperParam("");
        sysOperLog.setJsonResult("test,test");
        sysOperLog.setStatus(1);
        sysOperLog.setErrorMsg("测试");
        sysOperLog.setOperTime(new Date());
        try{
//            log.info("当前 XID: {}", RootContext.getXID());
            remoteLogService.saveLog(sysOperLog, SecurityConstants.INNER);
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new ServiceException("异常!");
//        return AjaxResult.error("失败");
    }
}
